let config = {};
const fs = require("fs");
let DataTypes = {
  integer: "number",
  number: "number",
  string: "string",
  boolean: "boolean",
  array: "Array",
  object: "object",
};
const gen = () => {
  const baseUrl = "../";
  config = require(baseUrl + "apicodegen.js");
  const axios = require("axios");
  for (const project of config.projects) {
    axios.get(project.docsUrl).then((res) => {
      let paths = res.paths;
      let definitions = res.definitions;
      genAllType(definitions, config.savePath + "/" + project.name);
      genPath(paths, project, config.savePath + "/" + project.name);
    });
  }
};

function getParameters(parameters) {
  let param = {
    name: "inVo",
    in: "body", // "query", "header", "path", "formData" or "body".
    description: "inVo",
    required: true, // true false
    /* 当 in 为 body */
    schema: {
      $ref: "#/definitions/GoodsCateogoryWordListInVo",
      originalRef: "GoodsCateogoryWordListInVo",
    },
    schema: {
      type: "array",
      items: {
        type: "string",
      },
    },
    /* 当 in 为 其他值 */
    type: "", // "string", "number", "integer", "boolean", "array" or "file"
    format: "",
    items: {}, // required if type is array.Describes the type of items in the array.
  };
  if (parameters.length === 0) {
    return null;
  }
  parameters.forEach((param) => {
    if (param.in === "body") {
      let bodySchema;
      if (param.schema.$ref) {
        bodySchema = config.definitions[schema.originalRef];
        bodySchemaToType(bodySchema);
      } else {
        bodySchema = param.schema;
      }
    } else {
    }
    let schema = param.schema;
  });
}

function bodySchemaToType(schema) {
  // schema.properties.type
  if (schema.type === "object") {
    Object.keys(schema.properties).forEach((key) => {
      let value = schema.properties[key];
      let str = "";
      if (Object.prototype.toString.call(value) === "[object Object]") {
        str += `${key}?: ${
          value.originalRef ? value.originalRef : DataTypes[value.type]
        }; /* ${value.description} */
        `;
      }
    });
  }
  let typeStr = `
  Interface ${schema.title} {
    ${str}
  };
  `;
  console.log(typeStr);
}

function genFile(path, url, parameters) {}

function genAllType(definitions, path) {
  let result = "";
  path = path + "/Entity.ts";
  Object.values(definitions).forEach((v) => {
    if (Object.prototype.toString.call(v) === "[object Object]") {
      result += propertyToEntity(v);
    }
  });
  writeFile(path, result);
}
function getArrayItemsType(items) {
  if (items.items) {
    let type = getArrayItemsType(items.items);
    return `Array<${type}>`;
  } else {
    if (items.originalRef) {
      return `Array<${items.originalRef}>`;
    } else {
      return `Array<${DataTypes[items.type]}>`;
    }
  }
}
function propertyToEntity(property) {
  let content = "";
  if (property.type === "object") {
    Object.keys(property.properties).forEach((key) => {
      let value = property.properties[key];
      let required = (property.required || []).includes(key) ? "?" : "";
      let description = value.description ? `/* ${value.description} */` : "";
      if (value.type == null) {
        let valueStr = "object";
        if (value.$ref) {
          // [].at() 报错
          let arr = value.$ref.split("/");
          valueStr = arr[arr.length - 1];
        }
        content += `${key}${required}: ${valueStr}; ${description}
    `;
      } else if (value.type == "array") {
        content += `${key}${required}: ${getArrayItemsType(
          value.items
        )}; ${description}
    `;
      } else if (value.type == "object") {
        content += `${key}${required}: object; ${description}
    `;
      } else if (value.type == "file") {
        content += `${key}${required}: File; ${description}
    `;
      } else {
        content += `${key}${required}: ${DataTypes[value.type]}; ${description}
    `;
      }
    });
  }
  let title = property.title.replace(/«/g, "").replace(/»/g, "");
  return `interface ${title} {
    ${content}};


  `;
}

function genPath(paths, project, path) {
  path = path + "/Entity.ts";
  Object.keys(paths).forEach((key) => {
    let value = paths[key];
    project.children.forEach((child) => {
      if (key.startsWith(child.name) /* includes|excludes */) {
        Object.keys(value).forEach((methodType) => {
          if (child.methods.includes(methodType)) {
          }
        });
      }
    });
  });
}
/*
export function getFilterByCode(paramsOrData: any, headers, options): Promise<any> {
  return request({
    url: "/sku_on_sale/getFilterByCode",
    method: "get",
    data: paramsOrData,
    params: paramsOrData,
    ...options,
  });
}
*/
function genAllPath(pathsObj) {
  fnstr = ``;
  Object.keys(pathsObj).forEach((key) => {
    let _description,
      _fnName,
      _params,
      _data,
      _url,
      _method,
      _headers,
      _headerType;
    _url = key;
    _fnName = _url.split("/").reverse()[0];
    Object.keys(pathsObj[key]).forEach((method) => {
      _method = method;
      let apiDescribe = pathsObj[key][method];
      _description = apiDescribe.summary;
      let { paramStr, headerStr, bodyStr, headerType } = buildParameter(
        apiDescribe.parameters,
        _fnName
      );
      _params = paramStr;
      _data = bodyStr;
      _headers = headerStr;
      _headerType = headerType;
    });
    fnstr += `
    ${headerType}
    /* ${_description} */
    export function ${_fnName}(${_params}, ${_data}, ${_headers}, options): Promise<any> {
      return request({
        url: "${_url}",
        method: "${_method}",
        data: ${_data},
        params: ${_params},
        ...options,
      });
    }

    `;
  });
  writeFile("../fn.ts", fnstr);
}

/*
interface header {

}
*/
function buildParameter(parameters, name) {
  let paramStr = ``;
  let headerStr = ``;
  let bodyStr = ``;
  parameters.forEach((param) => {
    let required = param.required ? "" : "?";
    if (param.in === "query") {
      paramStr += `${param.name}${required}: ${param.type}, `;
    } else if (param.in === "header") {
      headerStr += `${param.name}${required}: ${param.type};
    `;
    } else if (param.in === "body") {
      bodyStr += `${param.name}${required}: ${getSchema(param.schema)}, `;
    }
  });
  let header = `
  /*
    interface ${name}Header {
      ${headerItem}}
  */ 
  `;
  return {
    paramStr,
    headerStr,
    bodyStr,
    headerType: header,
  };
}

function getSchema(schema) {
  if (schema.type === "array") {
    return `Array<${schema.items.originalRef}>`;
  } else {
    return `${schema.originalRef}`;
  }
}
function writeFile(path, content) {
  fs.writeFile(path, content, function (err) {
    if (err) {
      return console.error(err);
    }
    console.log("数据写入成功！");
    fs.readFile(path, function (err, data) {
      if (err) {
        return console.error(err);
      }
      console.log("异步读取文件数据: ");
      // data.toString()
    });
  });
}

genAllPath();
module.exports = {
  gen,
};
